home *** CD-ROM | disk | FTP | other *** search
/ Graphics & Sound Program…ng Techniques for the Mac / Graphics and Sound Programming Techniques for the Mac.iso / Goodies / Animation Libraries / GENetRelease2ƒ / GEDemo / GEDemo.c < prev    next >
C/C++ Source or Header  |  1994-06-01  |  18KB  |  835 lines

  1. /*
  2.     GEDemo.c
  3.     
  4.     Demo program for Graphic Elements library
  5.     
  6.     11/1/93
  7.     
  8.     Al Evans
  9. */
  10.  
  11. #ifdef applec
  12. #ifndef PRELOAD
  13. #pragma load "::ToolKit.precompile"
  14. #define PRELOAD
  15. #endif
  16. #else
  17. #include <QDOffscreen.h>
  18. #endif
  19.  
  20. #include <Timer.h>
  21. #include <GestaltEqu.h>
  22.  
  23. #include "GUtilities.h"
  24. #include "GrowWindConst.h"
  25. #include "GraphElements.h"
  26. #include "Sensors.h"
  27. #include "Cannon.h"
  28. #include "Walk.h"
  29. #include "Pogo.h"
  30. #include "Sign.h"
  31. #include "Meter.h"
  32. #include "Grabber.h"
  33.  
  34. //define HISTOGRAM to collect times history
  35. #undef HISTOGRAM
  36.  
  37. #ifdef HISTOGRAM
  38. #include "StdIO.h"
  39. #endif
  40.  
  41. //define PERFORMANCE to collect profiling data
  42. #undef PERFORMANCE
  43. #ifdef PERFORMANCE
  44. #include <Perf.h>
  45. #endif
  46.  
  47.  
  48. //Menu Commands
  49.  
  50. #define    rMenuBar                128        /* application's menu bar */
  51.  
  52. #define    mApple                    128        /* Apple menu */
  53. #define    iAbout                    1
  54.  
  55. #define    mFile                    129        /* File menu */
  56. #define    iQuit                    1
  57.  
  58. #define    mEdit                    130        /* Edit menu */
  59. #define    iUndo                    1
  60. #define    iCut                    3
  61. #define    iCopy                    4
  62. #define    iPaste                    5
  63. #define    iClear                    6
  64.  
  65. #define mSpecial                131
  66. #define iShoot                    1
  67. #define iSingleFrame            2
  68. #define iSignText                3
  69. #define iSpeed                    4
  70. #define iGrabber                5
  71.  
  72.  
  73. #define    rAboutDialog    228        
  74. #define rUserAlert        129
  75. #define rSetTextDialog    135
  76. #define rFrameRateDialog 130
  77. #define rSpeedDialog    131
  78.  
  79. //Resource numbers of graphic PICTs
  80. #define    rBrickPic 200
  81.  
  82. //Number of master pointer blocks needed
  83.  
  84. #define masterBlocksNeeded 10
  85.  
  86. //Globals
  87.  
  88. #ifdef PERFORMANCE
  89. TP2PerfGlobals        thePGlobals;
  90. #endif
  91.  
  92. Boolean        gFinished;
  93. WindowPtr    gAnimWindow;
  94. Boolean        gSingleFrame = false;
  95. Boolean        gDoOne = false;
  96. Rect        gWorldBaseRect;
  97. Rect        gWorldLimRect;
  98.  
  99.  
  100. //Performance measurement
  101.  
  102. #define thirtySeconds 30L * 1000 * 1000        //µsec for timers -- never time out
  103.  
  104. TMTask    gTTimeTask, gATimeTask;
  105. unsigned long gTotalTime = 0, gAnimTime = 0;
  106.  
  107. #ifdef HISTOGRAM
  108. long    animTimes[100];
  109. long    mainTimes[100];
  110. #endif
  111.  
  112. //Forward declarations
  113.  
  114. #ifdef applec
  115. extern void _DataInit();    //reference so that we can unload it
  116. #endif
  117.  
  118. Boolean Initialize( void );
  119. void Shutdown(void);
  120. void EventLoop( void );
  121.  
  122. main()
  123. {
  124. #ifdef applec
  125.     UnloadSeg((Ptr) _DataInit);
  126. #endif
  127.     MaxApplZone();
  128.     if ( Initialize() )
  129.         EventLoop();
  130.     Shutdown();
  131. }
  132.  
  133.  
  134. //Initialization
  135.  
  136. Boolean AdequateSystem(void)
  137. {
  138.     OSErr        err;
  139.     long        response;
  140.     Boolean        ok;
  141.     
  142.     //We need 68020 or better
  143.     err = Gestalt(gestaltProcessorType, &response);
  144.     ok = (!err) & (response >= gestalt68020);
  145.     
  146.     //We need System 7 or later
  147.     err = Gestalt(gestaltSystemVersion, &response);
  148.     ok = (!err) & (((response & 0xFFFF) / 256) >= 7);
  149.     
  150.     //We need color QD & offscreen GWorlds
  151.     err = Gestalt(gestaltQuickdrawVersion, &response);
  152.     ok = ok & (!err) & (response >= gestalt32BitQD);
  153.     err = Gestalt(gestaltQuickdrawFeatures, &response);
  154.     ok = ok & (!err) & (response >= 3);         //hasColor & deep GWorlds
  155.     
  156.     return ok;
  157.     
  158. }
  159.  
  160. //Make window centered on main graphic device
  161. WindowPtr MakeWindow(short wHSize, short wVSize)
  162. {
  163.     GDHandle    mainDevice;
  164.     Rect        devRect;
  165.     short        hOffst, vOffst;
  166.     Rect        windRect;
  167.     
  168.     mainDevice = GetMainDevice();
  169.     devRect = (**mainDevice).gdRect;
  170.     gWorldLimRect.top = wVSize / 2;
  171.     gWorldLimRect.left = wHSize / 2;
  172.     gWorldLimRect.bottom = RectHeight(&devRect);
  173.     gWorldLimRect.right = RectWidth(&devRect);
  174.     hOffst = (RectWidth(&devRect) - wHSize) / 2;
  175.     if (hOffst < 0) hOffst = 0;
  176.     vOffst = (RectHeight(&devRect) - wVSize) / 2;
  177.     if (vOffst < 0 ) vOffst = 0;
  178.     windRect.left = hOffst;
  179.     windRect.right = hOffst + wHSize;
  180.     windRect.top = vOffst;
  181.     windRect.bottom = vOffst + wVSize; 
  182.     
  183.     return NewCWindow(nil, &windRect, "\pAnimation Demo", false, documentProc,
  184.                         (WindowPtr) -1L, false, 0L);
  185. }
  186.  
  187.  
  188.  
  189. void InitPerformanceTiming(void)
  190. {
  191.     //Init Timers
  192.     gTTimeTask.tmAddr = nil;
  193.     gTTimeTask.tmWakeUp = 0;
  194.     gTTimeTask.tmReserved = 0;
  195.     
  196.     gATimeTask.tmAddr =  nil;
  197.     gATimeTask.tmWakeUp = 0;
  198.     gATimeTask.tmReserved = 0;
  199.     
  200. }
  201.  
  202. Boolean LoadBackground(GEWorldPtr world)
  203. {
  204.     GrafElPtr    bkg;
  205.     if (bkg = NewBasicPICT(world, 'BKG ', 1, rBrickPic, srcCopy, 0, 0))
  206.         return true;
  207.     return false;
  208. }
  209.  
  210. Boolean AddGrowBox(GEWorldPtr world)
  211. {
  212.     GrafElPtr    growBox;
  213.     
  214.     growBox = NewBasicPICT(world, 'GBOX', 32100, 20000, srcCopy, 
  215.                         gWorldBaseRect.right - 15, gWorldBaseRect.bottom - 15);
  216.     return (growBox != nil);
  217. }
  218.  
  219. Boolean InitializeGEWorld(WindowPtr window, Rect * refRect, Rect *actRect)
  220. {
  221.     Fixed        propH, propV;
  222.     Fixed        worldScale;
  223.     GEWorldPtr    animWorld;
  224.     
  225.     propH = (RectWidth(actRect) * 65536) / RectWidth(refRect);
  226.     propV = (RectHeight(actRect) * 65536) / RectHeight(refRect);
  227.     worldScale = (propH > propV?propH:propV);
  228.     
  229.     animWorld = NewGEWorld(window, refRect, worldScale , nil);
  230.     if (animWorld == nil) {
  231.         TellUser("\pCould not create new GEWorld.", 0);
  232.         return false;
  233.     }
  234.     SetWRefCon(window, (long) animWorld);
  235.     
  236.     //Load graphics
  237.     
  238.     if (!LoadBackground(animWorld)) {
  239.         TellUser("\pCould not load background", 0);
  240.         return false;
  241.     }
  242.     if (!LoadCannonScene(animWorld)) {
  243.         TellUser("\pCould not load cannon scene", 0);
  244.         return false;
  245.     }
  246.     
  247.     if (!LoadBalconyScene(animWorld)) {
  248.         TellUser("\pCould not load animated walk", 0);
  249.         return false;
  250.     }
  251.     
  252.     if (!LoadPogoScene(animWorld)) {
  253.         TellUser("\pCould not load pogo stick", 0);
  254.         return false;
  255.     }
  256.     
  257.     if (!LoadSignScene(animWorld)) {
  258.         TellUser("\pCould not load sign", 0);
  259.         return false;
  260.     }
  261.     
  262.     if (!LoadUsageMeterScene(animWorld)) {
  263.         TellUser("\pCould not load usage meter", 0);
  264.         return false;
  265.     }
  266.     if (!MakeGrabber(animWorld)) {
  267.         TellUser("\pCould not create grabber", 0);
  268.         return false;
  269.     }
  270.     if (!AddGrowBox(animWorld)) {
  271.         TellUser("\pCould not add grow box", 0);
  272.         return false;
  273.     }
  274.     return true;
  275. }
  276.     
  277. void ChangeWorldSize(WindowPtr window, short newWidth, short newHeight)
  278. {
  279.     Rect    animRect;
  280.     
  281.     ActivateWorld((GEWorldPtr) GetWRefCon(window), false);
  282.  
  283.     DisposeGEWorld((GEWorldPtr) GetWRefCon(window));
  284.     SetRect(&animRect, 0, 0, newWidth, newHeight);
  285.     if (!InitializeGEWorld(window, &gWorldBaseRect, &animRect)) {
  286.         TellUser("\pCould not resize animated world.", 0);
  287.         ExitToShell();
  288.     }
  289.     ActivateWorld((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  290. }
  291.  
  292. Boolean Initialize(void)
  293. {
  294.     Rect        animRect;
  295.     GEWorldPtr    animWorld;
  296. #ifdef HISTOGRAM
  297.     short    count;
  298. #endif
  299.     
  300.     gFinished = false;
  301.     
  302.     InitSystem(masterBlocksNeeded);
  303.     
  304.     
  305.     if (!AdequateSystem()) {
  306.         TellUser("\pSorry, more powerful system required", 0);
  307.         return false;
  308.     }
  309.     if (!LoadMenus(rMenuBar)) {
  310.         TellUser("\pCould not load menus", 0);
  311.         return false;
  312.     }
  313.     
  314.     gAnimWindow = MakeWindow(512, 364);
  315.     if (gAnimWindow == nil) {
  316.         TellUser("\pCould not create window", 0);
  317.         return false;
  318.     }
  319.     SetRect(&gWorldBaseRect, 0, 0, 512, 364);
  320.     animRect = gWorldBaseRect;
  321.     
  322.     if (!InitializeGEWorld(gAnimWindow, &gWorldBaseRect, &animRect)) {
  323.         TellUser("\pCould not create animated world.", 0);
  324.         return false;
  325.     }
  326.     
  327.     InitPerformanceTiming();
  328.     
  329. #ifdef HISTOGRAM
  330.     for (count = 0; count < 100; count++) {
  331.         animTimes[count] = 0;
  332.         mainTimes[count] = 0;
  333.     }
  334. #endif
  335.     
  336. #ifdef PERFORMANCE
  337.     thePGlobals = nil;
  338.     if (!InitPerf( &thePGlobals, 10, 8, true, true, "\pCODE", 0, "\p", false, 0L, 0L, 0) ){
  339.         TellUser("\pCould not initialize profiling", 0);
  340.         return false;
  341.     }
  342. #endif
  343.     
  344.     //Turn animation on and show window
  345.     ActivateWorld((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  346.     ShowWindow(gAnimWindow);
  347.     
  348. }
  349.  
  350. #ifdef HISTOGRAM
  351. void DumpHistograms(void)
  352. {
  353.     short    count;
  354.     FILE*    dump;
  355.     
  356.     dump = fopen("HistoDump", "w");
  357.     for (count = 0; count < 100; count++) 
  358.         fprintf(dump, "%d\t%d\t%d\n", count, mainTimes[count], animTimes[count]);
  359.     fflush(dump);
  360.     fclose(dump);
  361. }
  362. #endif
  363.  
  364. void Shutdown(void)
  365. {
  366.     GEWorldPtr world = (GEWorldPtr) GetWRefCon(gAnimWindow);
  367. #ifdef PERFORMANCE
  368.     OSErr err;
  369. #endif
  370.     //Release system resources
  371.     
  372. #ifdef HISTOGRAM
  373.     DumpHistograms();
  374. #endif
  375. #ifdef PERFORMANCE
  376.     err = PerfDump(thePGlobals, "\pPerform.out", false, 0);
  377. #endif
  378.     if (world)
  379.         DisposeGEWorld(world);
  380.     ExitToShell();
  381. }
  382.  
  383. #ifdef HISTOGRAM
  384.  
  385. void RunMeterAnimation(void)
  386. {
  387.     static short    setting = 0;
  388.     short            thisSetting;
  389.     if ((gTotalTime - gAnimTime) < 100)
  390.         mainTimes[(gTotalTime - gAnimTime)]++;
  391.     else
  392.         mainTimes[99]++;
  393.     if (gAnimTime < 100)
  394.         animTimes[gAnimTime]++;
  395.     else
  396.         animTimes[99]++;
  397.     
  398.     if (gTotalTime == 0) gTotalTime = 1;
  399.     thisSetting = (gAnimTime * 100) / gTotalTime;
  400.     if (thisSetting == setting)
  401.         return;
  402.     if (thisSetting > setting)
  403.         setting++;
  404.     else
  405.         if (thisSetting < setting)
  406.             setting--;
  407.     SetMeterReading((GEWorldPtr) GetWRefCon(gAnimWindow), setting);
  408. }    
  409.  
  410. #else
  411.  
  412. void RunMeterAnimation(void)
  413. {
  414.     static short    setting = 0;
  415.     short            thisSetting;
  416.     
  417.     if (gTotalTime == 0) gTotalTime = 1;
  418.     thisSetting = (gAnimTime * 100) / gTotalTime;
  419.     if (thisSetting == setting)
  420.         return;
  421.     if (thisSetting > setting)
  422.         setting++;
  423.     else
  424.         if (thisSetting < setting)
  425.             setting--;
  426.     SetMeterReading((GEWorldPtr) GetWRefCon(gAnimWindow), setting);
  427.     
  428. }
  429. #endif
  430.  
  431. void DoTimingLoop(void)
  432. {
  433. }
  434.  
  435. pascal Boolean SignFilter(DialogPtr dialog, EventRecord *event, short *item)
  436. {
  437. #pragma unused (dialog)
  438.  
  439. TEHandle    text;
  440.     
  441.     if ((event->what == keyDown) || (event->what == autoKey)) {
  442.         switch (event->message & charCodeMask) {
  443.         case 0x0d:
  444.         case 0x03:
  445.             *item = ok;
  446.             return true;
  447.             break;
  448.         case 0x1b:
  449.             *item = cancel;
  450.             return true;
  451.             break;
  452.         default:
  453.             text = ((DialogPeek) dialog)->textH;
  454.             //If 15 chars already and trying to insert
  455.             if ((GetHandleSize((**text).hText) > 14) && ((**text).selStart == (**text).selEnd)) {
  456.                 SysBeep(3);
  457.                 *item = 4;
  458.                 return true;
  459.             }
  460.             else
  461.                 return false;
  462.         }
  463.     }
  464.     else return false;
  465. }
  466.  
  467. void DoSetSignText( void )
  468. {
  469.     DialogPtr     sgnDialog;
  470.     short        itemType;
  471.     Handle        item;
  472.     Rect        okRect;
  473.     Rect        itemRect;
  474.     short        itemHit;
  475.     Str255        signText;
  476. #if NEWHEADERS
  477.     ModalFilterUPP    signFilterPtr = NewModalFilterProc(SignFilter);
  478. #else
  479.     ModalFilterProcPtr        signFilterPtr = SignFilter;
  480. #endif
  481.     
  482.     
  483.     sgnDialog = GetNewDialog(rSetTextDialog, nil, (WindowPtr) -1L);
  484.     GetDItem(sgnDialog, ok, &itemType, &item, &okRect);
  485.     GetDItem(sgnDialog, 4, &itemType, &item, &itemRect);
  486.     GetSignText(signText);
  487.     SetIText(item, signText);
  488.     InsetRect(&okRect, -4, -4);
  489.     ShowWindow(sgnDialog);
  490.     SetPort( (GrafPtr) sgnDialog);
  491.     PenSize(3, 3);
  492.     FrameRoundRect(&okRect, 16, 16);
  493.     SelIText(sgnDialog, 4, 0, 32767);
  494.     do
  495.         ModalDialog(signFilterPtr, &itemHit);
  496.     while ( (itemHit != ok) && (itemHit != cancel) );
  497.     if (itemHit == ok) {
  498.         GetIText(item, signText);
  499.         SetSignText((GEWorldPtr) GetWRefCon(gAnimWindow), signText);
  500.     }
  501.     
  502.     DisposDialog(sgnDialog);
  503. #if FORPPC
  504.     DisposeRoutineDescriptor(signFilterPtr);
  505. #endif    
  506. }
  507.  
  508. void DoSetSpeed( void )
  509. {
  510.     DialogPtr spdDialog;
  511.     short        itemType;
  512.     Handle        item;
  513.     Rect        okRect;
  514.     Rect        itemRect;
  515.     short        itemHit;
  516.     Str255        tmrSpdStr;
  517.     long        timerSpeed;
  518.     
  519.     spdDialog = GetNewDialog(rSpeedDialog, nil, (WindowPtr) -1L);
  520.     GetDItem(spdDialog, ok, &itemType, &item, &okRect);
  521.     GetDItem(spdDialog, 4, &itemType, &item, &itemRect);
  522.     timerSpeed = GetGETimerRate((GEWorldPtr) GetWRefCon(gAnimWindow));
  523.     timerSpeed = (100 * timerSpeed) >> 16;
  524.     NumToString( (long) timerSpeed, tmrSpdStr);
  525.     SetIText(item, tmrSpdStr);
  526.     InsetRect(&okRect, -4, -4);
  527.     ShowWindow(spdDialog);
  528.     SetPort( (GrafPtr) spdDialog);
  529.     PenSize(3, 3);
  530.     FrameRoundRect(&okRect, 16, 16);
  531.     SelIText(spdDialog, 4, 0, 32767);
  532.     do
  533.         ModalDialog(nil, &itemHit);
  534.     while ( (itemHit != ok) && (itemHit != cancel) );
  535.     if (itemHit == ok) {
  536.         GetIText(item, tmrSpdStr);
  537.         StringToNum(tmrSpdStr, &timerSpeed);
  538.         timerSpeed = (timerSpeed << 16) / 100;
  539.         SetGETimerRate((GEWorldPtr) GetWRefCon(gAnimWindow), timerSpeed);
  540.     }
  541.     
  542.     DisposDialog(spdDialog);
  543. }
  544.  
  545. pascal Boolean AboutFilter(DialogPtr dialog, EventRecord *event, short *item)
  546. {
  547. #pragma unused (dialog)
  548.     DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), false);
  549.     if ((event->what == mouseDown) || (event->what == keyDown)) {
  550.         *item = ok;
  551.         return true;
  552.     }
  553.     else return false;
  554. }
  555.  
  556. void DoAboutBox(void)
  557. {
  558.     DialogPtr    aboutDialog;
  559.     short        itemHit;
  560. #if NEWHEADERS
  561.     ModalFilterUPP    aboutFilterPtr = NewModalFilterProc(AboutFilter);
  562. #else
  563.     ModalFilterProcPtr        aboutFilterPtr = AboutFilter;
  564. #endif
  565.     
  566.     
  567.     aboutDialog = GetNewDialog(rAboutDialog, nil, (WindowPtr) -1L);
  568.     ModalDialog(aboutFilterPtr, &itemHit);
  569.     DisposDialog(aboutDialog);
  570. #if FORPPC
  571.     DisposeRoutineDescriptor(aboutFilterPtr);
  572. #endif    
  573. }
  574.  
  575. //Event Handling
  576.  
  577. void EventLoop( void )
  578. {
  579.     Boolean        gotEvent;
  580.     EventRecord    event;
  581.     
  582.     void DoEvent (EventRecord *event);
  583.     void AdjustCursor( void);
  584.     
  585.     do {
  586.         InsTime( (QElemPtr) &gTTimeTask);
  587.         InsTime( (QElemPtr) &gATimeTask);
  588.         PrimeTime( (QElemPtr) &gTTimeTask, -thirtySeconds);
  589.         if (!gSingleFrame || gDoOne) {
  590.             PrimeTime( (QElemPtr) &gATimeTask, -thirtySeconds);
  591.             
  592. #ifdef PERFORMANCE
  593.             (void) PerfControl(thePGlobals, true);
  594. #endif
  595.  
  596.             DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), false);
  597.             
  598. #ifdef PERFORMANCE
  599.             (void) PerfControl(thePGlobals, false);
  600. #endif
  601.             RmvTime( (QElemPtr) &gATimeTask);
  602.             gAnimTime = (thirtySeconds + gATimeTask.tmCount) / 1000;
  603.             gDoOne = false;
  604.         }
  605.         AdjustCursor();
  606.         if (gotEvent = WaitNextEvent(everyEvent, &event, 0L, nil)) 
  607.             DoEvent(&event);
  608.         RmvTime( (QElemPtr) &gTTimeTask);
  609.         gTotalTime = (thirtySeconds + gTTimeTask.tmCount) / 1000; //milliseconds
  610.         RunMeterAnimation();
  611.         
  612.     } while (!gFinished);
  613. }
  614.  
  615. void DoEvent (EventRecord *event)
  616. {
  617.     short        part;
  618.     WindowPtr    window;
  619.     char        key;
  620.     long        newWSize;
  621.     
  622.     //Prototypes
  623.     void AdjustMenus( void );
  624.     void DoMenuCommand(long menuResult);
  625.     void DoActivate(WindowPtr window, Boolean becomingActive);
  626.     void DoUpdate(WindowPtr window);
  627.     
  628.     switch ( event->what ) {
  629.         case mouseDown:
  630.             part = FindWindow(event->where, &window);
  631.             switch ( part ) {
  632.                 case inMenuBar:
  633.                     StopGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  634.                     AdjustMenus();
  635.                     DoMenuCommand(MenuSelect(event->where));
  636.                     StartGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  637.                     break;
  638.                 case inSysWindow:
  639.                     SystemClick(event, window);
  640.                     break;
  641.                 case inContent:
  642.                     if ( window != FrontWindow() ) 
  643.                         SelectWindow(window);
  644.                     if (MouseDownInSensor((GEWorldPtr) GetWRefCon(gAnimWindow), event->where))
  645.                         ;;
  646.                     break;
  647.                 case inDrag:
  648.                     DragWindow(window, event->where, &qd.screenBits.bounds);
  649.                     break;
  650.                 case inGrow:
  651.                     newWSize = GrowWindowConstrained(window, event->where, 
  652.                                             &gWorldLimRect, &gWorldBaseRect);
  653.                     SizeWindow(window, LoWord(newWSize), HiWord(newWSize), true);
  654.                     ChangeWorldSize(window, LoWord(newWSize), HiWord(newWSize));
  655.                     InvalRect(&((GrafPtr)window)->portRect);
  656.                     break;
  657.  
  658.             }
  659.             break;
  660.         case keyDown:
  661.             key = event->message & charCodeMask;
  662.             if ( event->modifiers & cmdKey ) {
  663.                 StopGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  664.                 AdjustMenus();
  665.                 DoMenuCommand(MenuKey(key));
  666.                 StartGETimer((GEWorldPtr) GetWRefCon(gAnimWindow));
  667.             }
  668.             else {
  669.                 switch (key) {
  670.                     case 'U':
  671.                     case 'u':
  672.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 0, -50);
  673.                         break;
  674.                     case 'D':
  675.                     case 'd':
  676.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 0, 50);
  677.                         break;
  678.                     case 'R':
  679.                     case 'r':
  680.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), 50, 0);
  681.                         break;
  682.                     case 'L':
  683.                     case 'l':
  684.                         MoveGEWorld((GEWorldPtr) GetWRefCon(gAnimWindow), -50, 0);
  685.                         break;
  686.                 }
  687.             }
  688.             gDoOne = true;
  689.             break;
  690.         case activateEvt:
  691.             DoActivate((WindowPtr) event->message, (event->modifiers & activeFlag) != 0);
  692.             break;
  693.         case updateEvt:
  694.             DoUpdate((WindowPtr) event->message);
  695.             break;
  696.         case osEvt:
  697.             switch ((event->message >> 24) & 0x0FF) {
  698.                 case suspendResumeMessage:
  699.                     gInBackground = (event->message & resumeFlag) == 0;
  700.                     DoActivate(FrontWindow(), !gInBackground);
  701.                     break;
  702.             }
  703.             break;
  704.         }
  705. }
  706.  
  707. void DoActivate(WindowPtr window, Boolean becomingActive)
  708. {
  709. #pragma unused (window)
  710. #pragma unused (becomingActive)
  711.     //Could start and stop animation here
  712. }
  713.  
  714.  
  715. void DoUpdate(WindowPtr window)
  716. {
  717.     Rect geRect;
  718.     GEWorldPtr geWorld;
  719.  
  720.     if (window == gAnimWindow)
  721.     {
  722.         SetPort( (GrafPtr) window );
  723.         //Protect GEWorld rect before updating window, since we will draw it
  724.         geWorld = (GEWorldPtr) GetWRefCon(gAnimWindow);
  725.         geRect = geWorld->animationRect;
  726.         RectOffset(&geRect, geWorld->worldFocus.h, geWorld->worldFocus.v);
  727.         ValidRect(&geRect);
  728.         
  729.         BeginUpdate(window);
  730.             FillRgn(((GrafPtr) window)->visRgn, (ConstPatternParam) &qd.gray);
  731.         EndUpdate(window);
  732.         
  733.         DoWorldUpdate((GEWorldPtr) GetWRefCon(gAnimWindow), true);
  734.     }
  735. }
  736.  
  737. void AdjustMenus( void )
  738. {
  739.     WindowPtr    window;
  740.     MenuHandle    menu;
  741.     
  742.     window = FrontWindow();
  743.     
  744.     menu = GetMHandle(mFile);
  745.     EnableItem(menu, iQuit);
  746.  
  747.     menu = GetMHandle(mEdit);
  748.     if (window = gAnimWindow) {
  749.         DisableItem(menu, iUndo);
  750.         DisableItem(menu, iCut);
  751.         DisableItem(menu, iCopy);
  752.         DisableItem(menu, iClear);
  753.         DisableItem(menu, iPaste);
  754.     }
  755.     else {
  756.         EnableItem(menu, iUndo);
  757.         EnableItem(menu, iCut);
  758.         EnableItem(menu, iCopy);
  759.         EnableItem(menu, iClear);
  760.         EnableItem(menu, iPaste);
  761.     }
  762.     menu = GetMHandle(mSpecial);
  763.     //Set up special items!
  764.     CheckItem(menu, iSingleFrame, gSingleFrame);
  765.     CheckItem(menu, iGrabber, GrabberActive((GEWorldPtr) GetWRefCon(gAnimWindow)));
  766. }
  767.  
  768. void DoMenuCommand(long menuResult)
  769. {
  770.     short        menuID;
  771.     short        menuItem;
  772.     Str255        daName;
  773.     short        daRefNum;
  774.  
  775.     menuID = HiWord(menuResult);
  776.     menuItem = LoWord(menuResult);
  777.     switch ( menuID ) {
  778.         case mApple:
  779.             switch ( menuItem ) {
  780.                 case iAbout:
  781.                     DoAboutBox();
  782.                     break;
  783.                 default:            /* all other items in this menu are DAs */
  784.                     GetItem(GetMHandle(mApple), menuItem, daName);
  785.                     daRefNum = OpenDeskAcc(daName);
  786.                     break;
  787.             }
  788.             break;
  789.         case mFile:
  790.             if (menuItem == iQuit)
  791.                 gFinished = true;
  792.             break;
  793.         case mEdit:
  794.             (void) SystemEdit(menuItem-1);
  795.             break;
  796.         case mSpecial:
  797.             //Add special items
  798.             switch ( menuItem ) {
  799.                 case iShoot:
  800.                     ShootCannon((GEWorldPtr) GetWRefCon(gAnimWindow), sensorOn);
  801.                     break;
  802.                 case iSingleFrame:
  803.                     gSingleFrame = !gSingleFrame;
  804.                     break;
  805.                 case iSignText:
  806.                     DoSetSignText();
  807.                     break;
  808.                 case iSpeed:
  809.                     DoSetSpeed();
  810.                     break;
  811.                 case iGrabber:
  812.                     ActivateGrabber((GEWorldPtr) GetWRefCon(gAnimWindow), 
  813.                                     !GrabberActive((GEWorldPtr) GetWRefCon(gAnimWindow)));
  814.                     break;
  815.             }
  816.             break;
  817.     }
  818.     HiliteMenu(0);
  819. }
  820.  
  821. //Utility routines
  822.  
  823.  
  824. void AdjustCursor( void )
  825. {
  826.     WindowPtr    window;
  827.     
  828.     window = FrontWindow();
  829.     
  830.     if ( (window == gAnimWindow) && (!gInBackground) ) {
  831.         SetCursor(&qd.arrow);
  832.     }
  833. }
  834.  
  835.